package mymyoux.io.mserverconnectorClasses
{
	import mymyoux.core.IObject;
	import mymyoux.events.ErrorEvent;
	import mymyoux.events.MAdvSocketEvent;
	import mymyoux.events.MEventDispatcher;
	import mymyoux.events.MRoomEvent;
	import mymyoux.utils.StringUtils;
		/**
         * MRoom dispatche l'event created
         * quand le serveur lui indique que sa création est effectuée.
         * @eventType mymyoux.events.MRoomEvent
         */
        [Event(name="created", type="mymyoux.events.MRoomEvent")]
        /**
         * MRoom dispatche l'event data
         * quand une donnée est reçue dans la MRoom.
         * @eventType mymyoux.events.MRoomEvent
         */
        [Event(name="data", type="mymyoux.events.MRoomEvent")]
	 /**
	 * MRoom permet de communiquer dans un salon virtuel d'un MServer. Un objet MRoom est renvoyé grâce à la fonction addRoom d'un objet MServerConnector.
	 * @author Mymyoux
	 * @version 2.0
	 */
	public class MRoom extends MEventDispatcher implements IObject
	{
		/**
		 * @private
		 */
		protected var _name:String;
		/**
		 * Boolean indiquant si oui ou non le salon a été détruit.
		 */
		protected var _destroyed:Boolean;
		/**
		 * MAdvSocket où se trouve le salon
		 */
		protected var socket:MAdvSocket;
		/**
		 * @private
		 */
		 protected var playlist:MRoomPlaylist;
		/**
		 * Crée un nouvel objet MRoom
		 * @param	name	Nom du salon
		 * @param	s	MAdvSocket associé au salon
		 * @param playlist Playlist du MServerConnector
		 */
		public function MRoom(name:String,s:MAdvSocket,playlist:MPlaylist)
		{
			this.playlist=new MRoomPlaylist(name,playlist);
			_destroyed=false;
			_name=name;
			socket=s;
			//this.playlist.id=s.id;
			socket.addEventListener(MAdvSocketEvent.CLOSE,onSocketClose);
			socket.addEventListener(MAdvSocketEvent.CONNECT,onSocketConnect);
			socket.addEventListener(MAdvSocketEvent.IDENTIFIED,onIdentified);
			socket.addEventListener(MAdvSocketEvent.DATA+_name,onData);
			enter();
		}
		/**
		 * Appelée lorsque le MAdvSocket associé à la MRoom reçoit des données pour celle-ci.
		 * @param e MAdvSocketEvent associé aux données reçues.
		 */
		protected function onData(e:MAdvSocketEvent):void{
			if(e.value.indexOf(":")>=0){
				var action:String=e.value.substring(0,e.value.indexOf(":"));
				var message:String=e.value.substring(e.value.indexOf(":")+1);
				dispatchEvent(new MRoomEvent(MRoomEvent.DATA,action,message,playlist.getPeople(e.id)));
			}
		}
		/**
		 * MRoomPlaylist gérant la liste des joueurs du salon.
		 */
		 public function get contacts():MRoomPlaylist{
		 	return playlist;
		 }
		/**
		 * Rejoint un salon du MAdvSocket. Si celui ci n'était pas connecté, la connexion est initialisée.
		 * throws mymyoux.events.ErrorEvent Lève un exception si le port ou l'ip sont incorrects.
		 */
		protected function enter():void{
			if(!socket.connected){
				socket.start();
			}
			initialize();

		}
		/**
		 * Quitte un salon du MAdvSocket. Equivalent à <code class="prettyprint">destroy()</code>.
		 * @see #destroy()
		 */
		public function exit():void{
			destroy();
		}
		/**
		 * Permet d'envoyer une chaine au MServer lui indiquant qu'on souhaite rentré dans le salon <code class="prettyprint">_name</code>.
		 */
		protected function initialize():void{
			socket.send("g"+_name);
		}
		/**
		 * Appelée lorsque le MAdvSocket est connecté.
		 * @param MAdvSocketEvent Event envoyé par le MAdvSocket lors de sa connexion.
		 */
		protected function onSocketConnect(e:MAdvSocketEvent):void{
			//initialize();
			//TODO:dispatch MRoomEvent
		}
		/**
		 * Appelée lorsque le MAdvSocket est déconnecté.
		 * @param MAdvSocketEvent Event envoyé par le MAdvSocket lors de sa déconnexion.
		 */
		protected function onSocketClose(e:MAdvSocketEvent):void{
			initialize();
			//TODO:dispatch MRoomEvent
		}
		/**
		 * Appelée lorsque le MAdvSocket reçoit l'id du joueur.
		 * @param MAdvSocketEvent Event envoyé par le MAdvSocket lors de la réception de l'id.
		 */
		protected function onIdentified(e:MAdvSocketEvent):void{
			dispatchEvent(new MRoomEvent(name,MRoomEvent.CREATED,null,null));
		}
		/** 
		 * Permet d'envoyer un message à un joueur de la MRoom ou à toute la MRoom.
		 * @param action Le type d'action envoyée par le joueur.
		 * @param message Le message associé à l'action.
		 * @param destinataire Si spécifié le message sera envoyé exclusivement à ce destinataire. 
		 * Si destinataire vaut null alors le message sera envoyée à toute la MRoom.
		 */
		public function send(action:String,message:String,destinataire:MServerIdentifier=null):void{
			_throwErrorIfDestroyed();

			if(action.length>0 && message.length>0){
				var id_pers:uint=playlist.getId(destinataire);
				socket.send("s"+((id_pers>0)?":"+id_pers+"s":"")+_name.length+":"+_name+action+":"+message);
			}
		}
		/**
		 * Permet d'ajouter un listener associé à un action particulière lors de la réception d'un message.
		 * @param name Nom de l'action à écouter.
		 * @param listener Fonction servant d'écouteur.
		 * @param useCapture Boolean indiquant si l'écouteur doit capturer tous les évènements.
		 * @param priority Indique la priorité de l'écouteur.
		 * @param useWeakReference Indique si le lien est faible ou non.
		 */
		public function addActionListener(name:String,listener:Function,useCapture:Boolean=false,priority:int=0,useWeakReference:Boolean=false):void{
			addEventListener(MAdvSocketEvent.DATA+name,listener,useCapture,priority,useWeakReference);
		}
		/**
		 * Permet de supprimer un listener associé à un action particulière lors de la réception d'un message.
		 * @param name Nom de l'action écoutée.
		 * @param listener Fonction servant d'écouteur.
		 * @param useCapture Boolean indiquant si l'écouteur capturait tous les évènements.
		 */
		public function removeActionListener(name:String,listener:Function,useCapture:Boolean=false):void{
			removeEventListener(MAdvSocketEvent.DATA+name,listener,useCapture);
		}
		/**
		 * Nom du salon complet.
		 */
		public function get name():String{
			return _name;
		}
		/**
		 * Nom court du salon (sans la référence au MAdvSocket).
		 */
		 public function get shortName():String{
		 	var name:String=_name;
		 	if(StringUtils.count(name,"#")>=2){
					name=name.substring(name.indexOf("#",name.indexOf("#")+1)+1);
			}
			return name;
		 }
		/**
		 * @inheritDoc 
		 */
		public override function destroy():void{
			if(!_destroyed){
				socket.send("l"+_name);
				socket.removeEventListener(MAdvSocketEvent.CLOSE,onSocketClose);
				socket.dispatchEvent(new MAdvSocketEvent(MAdvSocketEvent.ROOM_CLOSED,_name));
			}
		}
		/**
		 * @inheritDoc 
		 */
		public override function equals(objet:IObject):Boolean{
			var name:String;
			try{
				return (objet as MRoom).name==_name;
			}catch(e:Error){
				return false;
			}
			finally{
				return false;
			}
		}
		/**
		 * Lève une erreur si le salon est fermé. Appelé par les fonctions publiques nécessitant que le salon soit encore ouvert.
		 * @throws mymyoux.events.ErrorEvent Renvoie une erreur si le salon a été fermé.
		 */
		protected function _throwErrorIfDestroyed():void{
			if(_destroyed){
				throw(new ErrorEvent("Salon fermé",8));
			}
		}
		/**
		 * @inheritDoc 
		 */
		public override function toString():String{
			return "[MRoom name=\""+_name+"\"]";
		}

	}
}